package game;
import java.util.ArrayList;

import fields.*;

public class Player extends Account {

		// Ting, som programmet skal huske om spilleren.
		private String name;
		private int field, choice;
		private boolean lost, active;
		public boolean inJail;
		
		private ArrayList<Fleet> fleets;
		private ArrayList<LaborCamp> laborcamps;
		private ArrayList<Territory> territories;
		
		private int jailEscapeCards;
		private int roundsInJail;
		private boolean[] isPrevious2RollsDouble;
		
		//Konstruktoer er den der laver et objekt fx. en spiller.
		public Player() {
			name="";
			choice=2;
			field=1;
			lost=false;			//S√¶ttes til true, hvis spillerens konto g√•r i 0.
			active=true;		//S√¶ttes til false, hvis spilleren taber.
			inJail=false;
			fleets = new ArrayList<Fleet>();
			laborcamps = new ArrayList<LaborCamp>();
			territories = new ArrayList<Territory>();
			jailEscapeCards = 0;
			roundsInJail = 0;
			this.isPrevious2RollsDouble = new boolean[2];
			this.isPrevious2RollsDouble[0] = false;
			this.isPrevious2RollsDouble[1] = false;
		}
		
		public boolean haveAmount(int amount){
			return amount<beholdning;
		}
		
		public boolean isPrevious2RollsDouble() {
			return this.isPrevious2RollsDouble[0] && this.isPrevious2RollsDouble[1];
		}
		
		public void setPrevious2RollsDouble(boolean lastRollDouble) {
			this.isPrevious2RollsDouble[0] = this.isPrevious2RollsDouble[1];
			this.isPrevious2RollsDouble[1] = lastRollDouble;
		}
		
		public int getRoundsInJail() {
			return this.roundsInJail;
		}
		
		public void addRoundInJail() {
			this.roundsInJail++;
		}
		public void setName(String name) {
			this.name=name;
		}
		
		public boolean compareName(String navn1) {
			boolean b=false;
			if (name.compareToIgnoreCase(navn1)==0) {
				b=true;
			}
			return b;
		}
		
		public void move(int move)
		{
			field += move;
			if (field>40) field=field%40;
			if (field==0) field=1;
		}
		
		public void moveToField(int fieldNr) {
			this.field = fieldNr;
			if (this.field>40) {
			this.field=this.field%40;
			}
			if (this.field==0) {
			this.field=1;
			}
		}
		
		public int getField()
		{
			return field;
		}
		
		public String getName() {
			return name;
		}	
		
		public boolean hasLost()
		{
			if (beholdning==0) lost=true;
			return lost;
		}
		
		public boolean isActive()
		{
			return active;
		}
		
		public void bankrupt()
		{
			active=false;
			for (int i=0; i<fleets.size(); i++)
			{
				fleets.get(i).forSale();
			}
			for (int i=0; i<laborcamps.size(); i++)
			{
				laborcamps.get(i).forSale();
			}
			for (int i=0; i<territories.size(); i++)
			{
				territories.get(i).forSale();
			}
		}
		
		public void addFleet(Fleet f)
		{
			fleets.add(f);
		}
		
		public int getFleets()
		{
			return fleets.size();
		}
		
		public void addLaborCamp(LaborCamp l)
		{
			laborcamps.add(l);
		}
		
		public int getLaborCamps()
		{
			return laborcamps.size();
		}
		
		public void addTerritory(Territory t)
		{
			territories.add(t);
		}
		
		public void setChoice(int a)
		{
			choice=a;
		}
		
		public int getChoice()
		{
			return choice;
		}
		
		public int getAccount()
		{
			return beholdning; //Test
		}
		
		public void setActive(boolean status)
		{
			active = status;
		}


			public void addJailEscapeCard() {
				this.jailEscapeCards++;
			}
	
			/**
			 *
			 * @return boolean true, if card usage success, false otherwise
			 */
			public boolean useJailEscapeCard() {
				if (jailEscapeCards>0) {
					jailEscapeCards--;
					return true;
				}
				return false;
			}
			public int getJailEscapeCardCount() {
				return jailEscapeCards;
			}
									
			public void leaveJailUsingCard() {
				this.useJailEscapeCard();
				this.leaveJail();
			}
			
			public void leaveJailUsingFine() {
				this.withdraw(50);
				this.leaveJail();
			}
			
			public void leaveJail() {
				this.inJail = false;
				this.setActive(true);
				this.setPrevious2RollsDouble(false);
				this.roundsInJail = 0;
			}
			public int[] getStreetsPlayerCanBuildIn(Gameboard board) {
				ArrayList<Integer>candidates =new ArrayList<Integer>();
				ArrayList<Integer>list= new ArrayList<Integer>();
				
			int[][] streets = board.getBoardStreets();
			for (int i=0; i<streets.length; i++) {
			int[] street = streets[i];
			boolean streetOwner = true;
			for (int j=0; j<street.length; j++) {
			streetOwner = streetOwner && this.isOwner(street[j], board);
			if(!streetOwner){
				break;
			}
				}
			if (streetOwner) {
				for (int j=0; j<street.length; j++) {
					if (board.getField(street[j]).canBuild()) {
						candidates.add(street[j]);
					}
				}
			}
		}
		for (int candidate:candidates) {
			int buildCost = board.getField(candidate).getHouseCost();
			if (!this.haveAmount(buildCost)) {
			continue;
			}
			int housesBuiltOnCandidate = board.getField(candidate).housesBuilt();
			boolean addCandidate = true;
			if (board.getField(candidate).housesBuilt() == 0 && !board.getField(candidate).isHotelBuilt()) {
				list.add(candidate);
			} else {
				int[] streetFields = board.getStreet(candidate);
				for(int field:streetFields) {
					if (board.getField(field).housesBuilt()<housesBuiltOnCandidate && !board.getField(field).isHotelBuilt()) {
						addCandidate = false;
						break;
					}
				}
				if (addCandidate) {
					list.add(candidate);
				}
			}
		}
		int[] streetsList = new int[list.size()];
		int index = 0;
		for (Integer st:list) {
			streetsList[index] = st;
			index++;
		}
		return streetsList;
	}
	
	public boolean isOwner(int field, Gameboard board) {
		if (board.getField(field).isOwner(this)) {
			return true;
		}
		return false;
	}

	public boolean canSellHouses() {
		for (Territory t: territories) {
			if (t.isHotelBuilt || t.housesBuilt>0) {
				return true;
			}
		}
		return false;
	}

	public boolean canMortgageProperty() {
		for (Territory t: territories) {
			if (!t.isMortgaged  && !t.isHotelBuilt() && t.housesBuilt()==0) {
				return true;
			}
		}
		for (Fleet f: fleets) {
			if (!f.isMortgaged) {
				return true;
			}
		}
		for (LaborCamp lc: laborcamps) {
			if (!lc.isMortgaged) {
				return true;
			}
		}
		return false;
	}

	public int[] getHousesAvailableToSell(Gameboard board) {
		ArrayList<Integer> candidates = new ArrayList<Integer>();
		ArrayList<Integer> fieldNrs = new ArrayList<Integer>();
		
		for (Territory t: territories) {
			if (t.isHotelBuilt || t.housesBuilt>0) {
				candidates.add(t.getNumber()+1);
			}
		}
		for (int x:candidates) {
			int housesBuiltOnX = board.getField(x).housesBuilt();
			boolean addCandidate = true;
			if (board.getField(x).isHotelBuilt()) {
				fieldNrs.add(x);
			} else {
				int[] streetFields = board.getStreet(x);
				for(int field:streetFields) {
					if (board.getField(field).housesBuilt()>housesBuiltOnX  || board.getField(field).isHotelBuilt()) {
						addCandidate = false;
						break;
					}
				}
				if (addCandidate) {
					fieldNrs.add(x);
				}
			}
		}
		int[] returnArray = new int[fieldNrs.size()];
		int i = 0;
		for (int fieldNr : fieldNrs ) {
			returnArray[i] = fieldNr;
			i++;
		}
		return returnArray;
	}

	public int[] getPropertiessAvailableToMortgage() {
		ArrayList<Integer> fieldNrs = new ArrayList<Integer>();
		for (Territory t: territories) {
			if (!t.isMortgaged && !t.isHotelBuilt() && t.housesBuilt()==0) {
				fieldNrs.add(t.getNumber()+1);
			}
		}
		for (Fleet f: fleets) {
			if (!f.isMortgaged) {
				fieldNrs.add(f.getNumber()+1);
			}
		}
		for (LaborCamp lc: laborcamps) {
			if (!lc.isMortgaged) {
				fieldNrs.add(lc.getNumber()+1);
			}
		}
		
		int[] returnArray = new int[fieldNrs.size()];
		int i = 0;
		for (int field : fieldNrs) {
			returnArray[i] = field;
			i++;
		}
		return returnArray;
	}

		public int[] getMortgagedProperties() {
			ArrayList<Integer> fieldNrs = new ArrayList<Integer>();
			for (Territory t: territories) {
				if (t.isMortgaged) {
					int cost = t.getBuyOutFromMortagePrice();
					if (this.haveAmount(cost)) {
					fieldNrs.add(t.getNumber()+1);
					}
				}
			}
				for (Fleet f: fleets) {
					if (f.isMortgaged) {
						int cost = f.getBuyOutFromMortagePrice();
						if (this.haveAmount(cost)) {
							fieldNrs.add(f.getNumber()+1);
						}
					}
				}
			for (LaborCamp lc: laborcamps) {
				if (lc.isMortgaged) {
					int cost = lc.getBuyOutFromMortagePrice();
					if (this.haveAmount(cost)) {
						fieldNrs.add(lc.getNumber()+1);
					}
				}
			}
			
			int[] returnArray = new int[fieldNrs.size()];
			int i = 0;
			for (int field : fieldNrs) {
				returnArray[i] = field;
				i++;
			}
			return returnArray;
	}

	
}